package com.erytech.linktalk.web.client.dataview;

import java.util.Date;

import com.erytech.linktalk.web.client.datasource.MessageDataSource;
import com.erytech.linktalk.web.client.datasource.MessageUpdateEvent;
import com.erytech.linktalk.web.client.datasource.SmileyChangeEvent;
import com.erytech.linktalk.web.client.datasource.UserUpdateEvent;
import com.erytech.linktalk.web.client.framework.DataUpdateEvent;
import com.erytech.linktalk.web.client.framework.DataView;
import com.erytech.linktalk.web.client.i18n.LocaleMessages;
import com.erytech.linktalk.web.client.service.MessageInfo;
import com.google.gwt.user.client.rpc.InvocationException;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class MessagesView extends DataView implements ClickListener,
		KeyboardListener {

	static int row = 0;
	
	DockPanel container = new DockPanel();

	FlexTable messageTable = new FlexTable();

	ScrollPanel scroller = new ScrollPanel(messageTable);

	VerticalPanel inputPanel = new VerticalPanel();

	HorizontalPanel inputHeaderPanel = new HorizontalPanel();
	
	ListBox saidToList = new ListBox();
	
	Label saidToLabel = new Label("Says to: ");
	
	TextArea inputArea = new TextArea();

	Image smileyImage;
	
	public MessagesView(final MessageDataSource ds) {
		super(ds);
		ds.getRoomDataSource().getSmileyDataSource().addDataUpdateListener(this);
		ds.getRoomDataSource().getUserDataSource().addDataUpdateListener(this);
		messageTable.setWidth("100%");

		scroller.setSize("100%", "100%");
		scroller.setStyleName("message-panel");
		
		saidToLabel.setStyleName("name-label");
		saidToList.setWidth("200px");
		saidToList.addItem(ds.getRoomDataSource().getUserDataSource().getSaidTo());
		saidToList.addChangeListener(new ChangeListener() {
			public void onChange(Widget sender) {
				String userName = saidToList.getItemText(saidToList.getSelectedIndex());
				ds.getRoomDataSource().getUserDataSource().saidTo(userName);
			}
		});
		
		smileyImage = new Image(ds.getRoomDataSource().getSmileyDataSource().getSmileySrc(0));
		smileyImage.setStyleName("smiley-image-outset");
		smileyImage.addClickListener(new ClickListener() {
			public void onClick(Widget sender) {
				smileyImage.setStyleName("smiley-image-inset");
				SmileyView view = new SmileyView(ds.getRoomDataSource().getSmileyDataSource());
				view.setPopupPosition(smileyImage.getAbsoluteLeft() + 32, smileyImage.getAbsoluteTop() - 120);
				view.show();
			}
		});

		inputArea.setWidth("100%");
		inputArea.setHeight("60px");
		inputArea.setStyleName("input-textarea");
		inputArea.addKeyboardListener(this);

		HorizontalPanel smileyPanel = new HorizontalPanel();
		smileyPanel.setHorizontalAlignment(HorizontalPanel.ALIGN_RIGHT);
		Label spaceLabel = new Label("");
		spaceLabel.setWidth("40px");
		smileyPanel.add(spaceLabel);
		smileyPanel.add(smileyImage);
		
		inputHeaderPanel.setHorizontalAlignment(HorizontalPanel.ALIGN_LEFT);
		inputHeaderPanel.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
		inputHeaderPanel.add(saidToLabel);
		inputHeaderPanel.add(saidToList);
		inputHeaderPanel.add(smileyPanel);
		inputHeaderPanel.setStyleName("input-header-panel");

		inputPanel.setHorizontalAlignment(VerticalPanel.ALIGN_LEFT);
		inputPanel.setVerticalAlignment(VerticalPanel.ALIGN_TOP);
		inputPanel.setWidth("100%");
		inputPanel.add(inputHeaderPanel);
		inputPanel.add(inputArea);
		
		container.add(scroller, DockPanel.CENTER);
		container.add(inputPanel, DockPanel.SOUTH);
		container.setCellHeight(scroller, "100%");
		container.setCellWidth(scroller, "100%");
		container.setCellWidth(inputPanel, "100%");
		container.setSize("100%", "100%");

		initWidget(container);
	}

	public void onClick(Widget widget) {
		submitMsg();
	}

	private void submitMsg() {
		String text = inputArea.getText();
		if (text == null || text.trim().length() == 0) {
			return;
		}
		inputArea.setText("");
		inputArea.setCursorPos(0);
		inputArea.setFocus(true);
		MessageInfo messageInfo = new MessageInfo();
		messageInfo.setBody(text);
		((MessageDataSource)getDataSource()).postMsg(messageInfo);
	}

	public void onKeyUp(Widget widget, char arg1, int arg2) {
		if (arg1 == KEY_ENTER) {
			submitMsg();
		}
	}

	public void onKeyPress(Widget arg0, char arg1, int arg2) {
	}

	public void onKeyDown(Widget arg0, char arg1, int arg2) {
	}

	public void onWindowResized() {
		scroller.setHeight((container.getOffsetHeight() - inputPanel
				.getOffsetHeight() - 4) + "px");
	}

	public void onDataUpdateEvent(DataUpdateEvent event) {
		if(event instanceof MessageUpdateEvent) {
			MessageUpdateEvent msgEvent = (MessageUpdateEvent)event;
			if(msgEvent.getType() == MessageUpdateEvent.POLL_SUCCESS) {
				MessageInfo[] messages = msgEvent.getMessages();
				for (int i = 0; i < messages.length; i++) {
					addRow(messages[i]);
				}
			} else if(msgEvent.getType() == MessageUpdateEvent.POST_SUCCESS) {
				//nothing to do.
			} else if(msgEvent.getType() == MessageUpdateEvent.POST_FAILURE) {
				MessageInfo errorMessage = new MessageInfo();
				if(msgEvent.getThrowable() instanceof InvocationException) {
					errorMessage.setBody(LocaleMessages.instance.errorConnection());
				}  else {
					errorMessage.setBody(LocaleMessages.instance.errorPostMessage());
				}
				errorMessage.setFrom(LocaleMessages.instance.system());
				errorMessage.setTo("ALL");
				errorMessage.setPostTime(new Date());
				addRow(errorMessage);
			} else if(msgEvent.getType() == MessageUpdateEvent.POLL_FAILURE) {
				MessageInfo errorMessage = new MessageInfo();
				if(msgEvent.getThrowable() instanceof InvocationException) {
					errorMessage.setBody(LocaleMessages.instance.errorConnection());
				}  else {
					errorMessage.setBody(LocaleMessages.instance.errorPollMessage());
				}
				errorMessage.setFrom(LocaleMessages.instance.system());
				errorMessage.setTo("ALL");
				errorMessage.setPostTime(new Date());
				addRow(errorMessage);
			}
		} else if(event instanceof UserUpdateEvent) {
			UserUpdateEvent userUpdateEvent = (UserUpdateEvent)event;
			if(userUpdateEvent.getType() == UserUpdateEvent.SAID_TO) {
				if( userUpdateEvent.getUserName().equals(
						saidToList.getItemText(saidToList.getSelectedIndex())) ) {
					return;
				}
				int count = saidToList.getItemCount();
				for (int i = 0; i < count; i++) {
					if(userUpdateEvent.getUserName().equals(saidToList.getItemText(i))) {
						saidToList.setSelectedIndex(i);
						return;
					}
				}
				saidToList.addItem(userUpdateEvent.getUserName());
				saidToList.setSelectedIndex(saidToList.getItemCount() -1);
			}
		} else if(event instanceof SmileyChangeEvent) {
			SmileyChangeEvent smileyChangeEvent = (SmileyChangeEvent)event;
			smileyImage.setStyleName("smiley-image-outset");
			inputArea.setText(inputArea.getText() + "#{" + smileyChangeEvent.getSelected() + "}");
			inputArea.setFocus(true);
			inputArea.setCursorPos(inputArea.getText().length());
		}
	}

	private void addRow(MessageInfo messageInfo) {
		MessageView messageView = new MessageView(messageInfo);
		messageTable.setWidget(row++, 0, messageView);
		adjustView();
	}
	
	private void adjustView() {
		int posY = (messageTable.getOffsetHeight() - scroller.getOffsetHeight());
		if (posY > 0) {
			scroller.setScrollPosition(posY);
		}
	}

	public void saidTo(String userName) {
		((MessageDataSource)getDataSource()).getRoomDataSource()
			.getUserDataSource().saidTo(userName);
	}
	
	class MessageView extends Composite implements ClickListener {
		
		HTML fromLink;
		
		HTML toLink;

		MessageInfo messageInfo;

		public MessageView(MessageInfo messageInfo) {
			this.messageInfo = messageInfo;
			HorizontalPanel outer = new HorizontalPanel();
			outer.setHorizontalAlignment(HorizontalPanel.ALIGN_LEFT);
			outer.setWidth("100%");
			
			HorizontalPanel inner = new HorizontalPanel();
			inner.setHorizontalAlignment(HorizontalPanel.ALIGN_LEFT);
			inner.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
			inner.setSpacing(2);
			Date postTime = messageInfo.getPostTime();
			inner.add(new Label("[" + format(postTime.getHours()) 
					+ ":" + format(postTime.getMinutes()) 
					+ ":" + format(postTime.getSeconds()) + "]"));
			fromLink = new HTML("<a href='javascript:;'>" + messageInfo.getFrom() + "</a> " + LocaleMessages.instance.saysTo() + " ");
			fromLink.addClickListener(this);
			inner.add(fromLink);
			
			toLink = new HTML("<a href='javascript:;'>" + messageInfo.getTo() + "</a> "  + LocaleMessages.instance.say());
			toLink.addClickListener(this);
			inner.add(toLink);
			
			HTML body = new HTML(BodyParser.parseMessage(messageInfo.getBody()));
			inner.add(body);
			
			outer.add(inner);
			initWidget(outer);
		}

		private String format(int i) {
			return (i < 10) ? ("0" + i) : ("" + i);
		}

		public void onClick(Widget sender) {
			if(sender == fromLink) {
				saidTo(messageInfo.getFrom());
			} else if(sender == toLink) {
				saidTo(messageInfo.getTo());
			} else {}
		}
	}

}